﻿Imports Model.Geometry

Namespace Midline
    Public Class Mid_Circle
        Private _startpt As Point3d
        Private _startm As Double
        Private _startOri As SingleVector
        Private _endpt As Point3d
        Private _endm As Double
        Private _endOri As SingleVector
        Private _LineType As LineTypeList
        Private _isturnright As Boolean
        Private _length As Double
        Private _midm As Double
        Private _midpt As Point3d
        Private _radius As Double
        Private _centerpt As Point3d
        Private _offset As Double

        Public Property startpt() As Point3d
            Get
                Return _startpt
            End Get
            Set(value As Point3d)
                _startpt = value
            End Set
        End Property

        Public Property startm() As Double
            Get
                Return _startm
            End Get
            Set(value As Double)
                _startm = value
            End Set
        End Property

        Public Property startOri() As SingleVector
            Get
                Return _startOri
            End Get
            Set(value As SingleVector)
                _startOri = value
            End Set
        End Property

        Public Property endpt() As Point3d
            Get
                Return _endpt
            End Get
            Set(value As Point3d)
                _endpt = value
            End Set
        End Property

        Public Property endm() As Double
            Get
                Return _endm
            End Get
            Set(value As Double)
                _endm = value
            End Set
        End Property

        Public Property endOri() As SingleVector
            Get
                Return _endOri
            End Get
            Set(value As SingleVector)
                _endOri = value
            End Set
        End Property

        Public Property LineType() As LineTypeList
            Get
                Return _LineType
            End Get
            Set(value As LineTypeList)
                _LineType = value
            End Set
        End Property

        Public Property isturnright() As Boolean
            Get
                Return _isturnright
            End Get
            Set(value As Boolean)
                _isturnright = value
            End Set
        End Property

        Public Property length() As Double
            Get
                Return _length
            End Get
            Set(value As Double)
                _length = value
            End Set
        End Property

        Public Property midm() As Double
            Get
                Return _midm
            End Get
            Set(value As Double)
                _midm = value
            End Set
        End Property

        Public Property midpt()
            Get
                Return _midpt
            End Get
            Set(value)
                _midpt = value
            End Set
        End Property

        Public Property radius() As Double
            Get
                Return _radius
            End Get
            Set(value As Double)
                _radius = value
            End Set
        End Property

        Public Property centerpt() As Point3d
            Get
                Return _centerpt
            End Get
            Set(value As Point3d)
                _centerpt = value
            End Set
        End Property

        Public Property offset() As Double
            Get
                Return _offset
            End Get
            Set(value As Double)
                _offset = value
            End Set
        End Property
        ''' <summary>
        ''' 构造函数
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
            LineType = LineTypeList.TypeCIRCLE
            startpt = New Point3d()
            startm = 0
            endpt = New Point3d()
            startOri = New SingleVector()
            endOri = New SingleVector()
            endm = 0
            radius = 0
            midpt = New Point3d()
            midm = 0
            isturnright = True
            length = 0
            centerpt = New Point3d()
        End Sub
        ''' <summary>
        ''' 初始化所有元素，获得圆曲线解析
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function initMyself(ByRef ob As Object)
            GetCenterpt()
            startOri = ob.endOri
            GetEndOri()
            Return Nothing
        End Function

        Public Function GetEndOri()
            Dim phi = length / radius
            If isturnright = True Then
                endOri.Azi = startOri.Azi + phi
            Else
                endOri.Azi = startOri.Azi - phi
            End If
            If endOri.Azi > 2 * Math.PI Then
                endOri.Azi -= 2 * Math.PI
            End If
            If endOri.Azi < 0 Then
                endOri.Azi += 2 * Math.PI
            End If
            endOri.GetVector()
            Return Nothing
        End Function
        ''' <summary>
        ''' 根据起止点和半径求圆心
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetCenterpt()
            Dim A, B, C As Double
            Dim Derta As Double
            Dim C1, C2 As Double
            C1 = (endpt.pow2for2d - startpt.pow2for2d) / (2 * (endpt.p_x - startpt.p_x))
            C2 = (endpt.p_y - startpt.p_y) / (endpt.p_x - startpt.p_x)
            A = C2 * C2 + 1
            B = 2 * startpt.p_x * C2 - 2 * C1 * C2 - 2 * startpt.p_y
            C = startpt.p_x * startpt.p_x - 2 * startpt.p_x * C1 + C1 * C1 + startpt.p_y * startpt.p_y - radius * radius
            Derta = B * B - 4 * A * C
            If Derta >= 0 Then
                Derta = Math.Pow(Derta, 0.5)
                Dim temp1, temp2 As New Point3d()
                temp1.p_y = (-B + Derta) / (2 * A)
                temp1.p_x = C1 - C2 * temp1.p_y
                temp2.p_y = (-B - Derta) / (2 * A)
                temp2.p_x = C1 - C2 * temp2.p_y
                If temp1.isonLorR(startpt, endpt) = isturnright Then
                    centerpt = temp1
                Else
                    centerpt = temp2
                End If
            Else
                MsgBox("求取圆心坐标出错！")
            End If
            Return Nothing
        End Function
        ''' <summary>
        ''' 通过里程计算坐标
        ''' </summary>
        ''' <param name="mil"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetPointByMileage(ByVal mil As Double, ByRef vec As SingleVector) As Point3d
            If mil > endm Then
                Return Nothing
            End If
            Dim alpha = length / radius         '转向角
            'Dim T = radius * Math.Tan(alpha / 2)                 '切线
            Dim difmil = mil - startm       '待求点与起始点的里程差
            Dim phi = difmil / radius       'φ
            Dim delta = phi / 2               'δ
            Dim currtalpha As Double
            Dim C As Double
            Dim currpt As New Point3d()
            Dim cc As Integer
            startOri.GetAzimuth()
            If isturnright = False Then
                currtalpha = startOri.Azi - delta
                vec.Azi = startOri.Azi - phi
                cc = -1
            Else
                currtalpha = startOri.Azi + delta
                vec.Azi = startOri.Azi + phi
                cc = 1
            End If
            If vec.Azi > 2 * Math.PI Then
                vec.Azi -= 2 * Math.PI
            ElseIf vec.Azi < 0 Then
                vec.Azi += 2 * Math.PI
            End If
            C = 2 * radius * Math.Sin(delta)
            currpt.p_y = startpt.p_y + C * Math.Cos(currtalpha)
            currpt.p_x = startpt.p_x + C * Math.Sin(currtalpha)
            currpt.p_z = startpt.p_z
            vec.GetVector()

            '通过偏移量计算隧道中心设计坐标
            Dim offsetAzi = vec.Azi + cc * Math.PI / 2
            currpt.p_y = currpt.p_y + offset * Math.Cos(offsetAzi)
            currpt.p_x = currpt.p_x + offset * Math.Sin(offsetAzi)
            Return currpt
        End Function
    End Class
End Namespace
